# -*- coding: utf-8 -*-
# &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
# odoo16
# QQ:35350428
# 邮件:35350428@qq.com
# 手机：13584935775
# 作者：'Amos'
# 公司网址： www.xodoo.cn
# Copyright 昆山一百计算机有限公司
# 日期：2023-09-16
# &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

from odoo import api, fields, models, tools, SUPERUSER_ID, _
from odoo.exceptions import AccessDenied, AccessError, UserError, ValidationError
import math
from datetime import datetime, timedelta
import logging
_logger = logging.getLogger(__name__)



class workflow_info(models.Model):
    _name = 'workflow.info'
    _description = '工作流审核'
    _order = 'id desc'

    def changeTime(self, allTime):
        day = 24 * 60 * 60
        hour = 60 * 60
        min = 60
        if allTime < 60:
            return u"%d秒" % math.ceil(allTime)
        elif allTime > day:
            days = divmod(allTime, day)
            return u"%d 天 %s" % (int(days[0]), self.changeTime(days[1]))
        elif allTime > hour:
            hours = divmod(allTime, hour)
            return '%d 小时 %s' % (int(hours[0]), self.changeTime(hours[1]))
        else:
            mins = divmod(allTime, min)
            return u"%d 分 %d 秒" % (int(mins[0]), math.ceil(mins[1]))

    def _compute_duration(self):
        for order in self:
            if order.start_date:
                d1 = order.start_date
                if order.end_date:
                    d2 = order.end_date
                    delta = d2 - d1
                    data = self.changeTime(delta.seconds)
                    order.duration = data

    start_state = fields.Char(string='从状态')
    end_state = fields.Char(string='到状态')
    name = fields.Char(string='名称')

    res_model = fields.Char(string='对象名称', )
    res_id = fields.Char(string='记录ID', )

    user_id = fields.Many2one('res.users', string='审批人')
    create_id = fields.Many2one('res.users', string='申请人')
    start_date = fields.Datetime(string='申请时间', default=fields.Datetime.now)
    end_date = fields.Datetime(string='审批日期')
    note = fields.Text('审批意见')
    message = fields.Text('申请说明')
    model_id = fields.Many2one('ir.model', string='对象')
    color = fields.Integer(string='颜色', default=0)
    form_view = fields.Char(string='视图地址')
    duration = fields.Char(string='耗时', compute='_compute_duration')
    sequence = fields.Integer(string='排序', default=10)

    parent_id = fields.Many2one('workflow.info', string='上级菜单')
    child_id = fields.One2many('workflow.info', 'parent_id', string='下级菜单')

    type = fields.Selection([
        ('串签', '串签'),
        ('并签', '并签'),
        ('汇签', '汇签'),
    ], string='类型', default='串签', help="""串签、并签、汇签，也就是
    串流、并流、择流。
    假设一份文件需要A、B两个主管来审批，那么，
    串签：A签完，才轮到B来签；一般A是小领导，B是大领导；
    并签：A和B是并列的，可同时签，但必须2人都要签；一般A和B是同一层级但不同部门领导
    汇签：A和B是并列的，但只需一个签就可以了；此处A、B就是完全等价的了""")

    state = fields.Selection([
        ('同意', '同意'),
        ('拒绝', '拒绝'),
        ('回退', '回退'),
        ('取回', '取回'),
        ('等待审批', '等待审批'),
        ('已关闭', '已关闭'),
        ('已提交', '已提交')
    ], string='审批状态', default='等待审批')

    #:::好建议是不是或签，并签，直接确认（你有最终确认权限是否直接审核，还是使用并签）
    version_id = fields.Char(string='版本', help='有一个确认其它版本作废')
    process_id = fields.Many2one('workflow.node', string='发启流程', ondelete='cascade', index=True, copy=False)

    # @api.constrains('start_state','end_state','state')
    # def _check_Only(self):
    #     for line in self:
    #         if line.state == '等待审批':
    #             domain = [('user_id', '=', line.user_id.id),('res_model', '=', line.res_model),('res_id', '=', line.res_id),('start_state', '=', line.start_state),('end_state', '=', line.end_state),('state', '=', '等待审批')]
    #             rows_count = self.sudo().search_count(domain)
    #             if rows_count >1:
    #                     raise ValidationError('警告：操作过快!')
    #     return True

    def read(self, fields=None, load='_classic_read'):
        """ 绕过当前ORM. """
        self.check_access_rule('read')
        return super(workflow_info, self).read(fields=fields, load=load)

    def unlink(self):
        for order in self:
            if order.end_date == False:
                if self._uid in [1, 2]:
                    pass
                else:
                    if order.create_id.id != self._uid:
                        raise UserError('%s:只能删除自己创建的工作流!' % order._description)
            else:
                if self._uid in [1, 2]:
                    pass
                else:
                    raise UserError('已处理的工作流不可删除!')
        return super(workflow_info, self).unlink()

    def go_workflow(self):
        context = dict(self.env.context or {})
        if self.form_view:
            return {
                'name': '审批',
                'view_type': 'form',
                'view_mode': 'form',
                'res_model': self.res_model,
                'view_id': self.env.ref(self.form_view).id,
                'type': 'ir.actions.act_window',
                'res_id': int(self.res_id),
                'context': context,
                'target': 'new'
            }
        return {
            'name': '审批',
            'view_type': 'form',
            'view_mode': 'form',
            'res_model': self.res_model,
            # 'view_id': self.env.ref('Amos_Base.view_form_message_wizard').id,
            'type': 'ir.actions.act_window',
            'res_id': int(self.res_id),
            'context': context,
            'target': 'new'
        }

    # def write(self, vals):
    #     if self._context.has_key('search_disable_custom_filters'):
    #         pass
    #     else:
    #         if self._context.has_key('search_default_my_workflow_wait'):
    #             raise UserError('不可拖动!')
    #
    #     return super(workflow_info, self).write(vals)

    def send_message(self, records, content, author_id, partner_ids):
        #::::发送审批消息
        url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
        lines = []
        for partner_id in partner_ids:
            pram = {
                'res_partner_id': partner_id,
            }
            lines.append((0, 0, pram))

        message = self.env['mail.message'].create({
            'record_name': records._description,
            'subject': records._description,
            'body': '',
            'type': 'notification',
            'message_type': 'notification',
            'res_id': records.id,
            'model': records._name,
            'subtype_id': 2,  # id=2 是备注
            'author_id': author_id,
            'notification_ids': lines,
        })
        location = '<a href="%s/mail/view?message_id=%s" target="_blank">%s</a><br>' % (url, message.id, records.name)
        values = {
            'body': location + ' ' + content,
        }
        message.sudo().write(values)
        #
        # values = {
        #     'mail_message_id': message.id,
        #     'res_partner_id': partner_ids,
        # }
        # self.env['mail.notification'].create(values)

        return message

    def create_workflow(self, records, parent_id, process_id, state_form, state_to, context):
        """
        创建下级用户工作流
        :param records:
        :param content:
        :return:
        """
        records_model = self.env['ir.model'].sudo().search([('model', '=', records._name)], limit=1)
        sequence = 1
        lines = []
        list = context['workflow_users_ids']
        for i in range(len(list)):
            # print("序号：%s   值：%s" % (i + 1, list[i]))
            if context.get('type') == '串签':
                if i == 0:
                    self.create_mail_activity(records, records_model.id, list[i], state_form, state_to)
            elif context.get('type') in ['并签', '汇签']:
                self.create_mail_activity(records, records_model.id, list[i], state_form, state_to)
            values = {
                'type': context['type'],
                'version_id': context['version_id'],
                'res_model': records._name,
                'res_id': records.id,
                'model_id': records_model.id,
                'name': records.name,
                'user_id': list[i],
                'end_date': datetime.now(),
                'start_state': state_form,
                'end_state': state_to,
                'note': '',
                'sequence': sequence,
                'parent_id': parent_id,
                'process_id': process_id,
            }
            sequence += 1
            lines.append(values)

        ids = self.env['workflow.info'].create(lines)
        return ids

    def create_mail_activity(self, records, model_id, user_id, state_form, state_to):
        """
        创建用户审批权限提醒
        :param records:
        :param model_id:
        :param user_id:
        :return:
        """
        values = {
            'activity_type_id': self.env.ref('workflow.mail_activity_data_approval').id,
            'res_model': records._name,
            'res_id': records.id,
            'res_model_id': model_id,
            'user_id': user_id,
            'date_deadline': datetime.now(),
            'summary': '单据审批',
            'note': '%s-%s' % (state_form, state_to),
        }
        activity = self.env['mail.activity'].sudo().create(values)
        return activity

    def write_workflow(self, records, state, context):
        """
        更新当前用户工作流
        :param records:
        :param content:
        :return:
        """

        if context['workflow_id'] != 0:
            if context.get('workflow_ids', []) == []:
                workflow = self.env['workflow.info'].sudo().browse(int(context['workflow_id']))
                #:::如果状态不同就执行关闭
                if workflow.type == '串签':
                    values = {
                        'state': state,
                        'end_date': datetime.now(),
                        'note': context['message'],
                    }
                    workflow.sudo().write(values)
                    #::::关闭消息 并触发下一个审批人
                    domain = [
                        ('res_model', '=', records._name),
                        ('res_id', '=', records.id),
                        ('user_id', '=', self._uid),
                        ('activity_type_id', '=', self.env.ref('workflow.mail_activity_data_approval').id),
                        ('summary', '=', '单据审批')
                    ]
                    activities = self.env['mail.activity'].search(domain, order="id asc", limit=1)

                    if activities:
                        activities.action_feedback(feedback='审批完成')
                        # TODO(amos): 触发下一个用户提醒
                        domain = [
                            ('id', '!=', int(context['workflow_id'])),
                            ('res_model', '=', records._name),
                            ('res_id', '=', records.id),
                            ('start_state', '=', workflow.start_state),
                            ('end_state', '=', workflow.end_state),
                            ('type', '=', '串签'),
                            ('state', '=', '等待审批'),
                        ]
                        next_workflow = self.env['workflow.info'].sudo().search(domain, order="sequence, id desc",
                                                                                limit=1)
                        if next_workflow:
                            self.create_mail_activity(records, workflow.model_id.id, next_workflow.user_id.id,
                                                      next_workflow.start_state, next_workflow.end_state)




                elif workflow.type == '汇签':
                    values = {
                        'state': state,
                        'end_date': datetime.now(),
                        'note': context['message'],
                    }
                    workflow.sudo().write(values)
                    #::::其它汇签 自动关闭
                    version = self.env['workflow.info'].sudo().search(
                        [('state', '=', '等待审批'), ('version_id', '=', workflow.version_id), ('id', '!=', workflow.id)])
                    version.write({'state': '已关闭', 'note': '由 %s 汇签' % workflow.user_id.name,
                                   'end_date': fields.Datetime.now()})
                    #::::发消息单据已完成
                    domain = [
                        ('res_model', '=', records._name),
                        ('res_id', '=', records.id),
                        ('user_id', '=', self._uid),
                        ('activity_type_id', '=', self.env.ref('workflow.mail_activity_data_approval').id),
                        ('summary', '=', '单据审批')
                    ]
                    activities = self.env['mail.activity'].search(domain, order="id asc", limit=1)

                    if activities:
                        activities.action_feedback(feedback='审批完成')

                        domain = [
                            ('res_model', '=', records._name),
                            ('res_id', '=', records.id),
                            ('activity_type_id', '=', self.env.ref('workflow.mail_activity_data_approval').id),
                            ('summary', '=', '单据审批')
                        ]
                        self.env['mail.activity'].search(domain, order="id asc", limit=1).action_feedback(
                            feedback='[%s]代签完成' % self.env.user.name)




                elif workflow.type == '并签':
                    domain = [
                        ('res_model', '=', records._name),
                        ('res_id', '=', records.id),
                        ('user_id', '=', self._uid),
                        ('state', '=', '等待审批'),
                    ]
                    workflow = self.env['workflow.info'].sudo().search(domain)
                    if workflow:
                        values = {
                            'state': state,
                            'end_date': datetime.now(),
                            'note': context['message'],
                        }
                        workflow.sudo().write(values)
                        # 更新自己的通知
                        domain = [
                            ('res_model', '=', records._name),
                            ('res_id', '=', records.id),
                            ('user_id', '=', self._uid),
                            ('activity_type_id', '=', self.env.ref('workflow.mail_activity_data_approval').id),
                            ('summary', '=', '单据审批')
                        ]
                        activities = self.env['mail.activity'].search(domain, order="id asc", limit=1)

                        if activities:
                            activities.action_feedback(feedback='审批完成')
                    else:
                        _logger.info('工作流错误 %s', str(domain))

    def create_workflow_ok(self, records, start_state, end_state, context):
        """
        创建下级用户工作流
        :param records:
        :param content:
        :return:
        """
        records_model = self.env['ir.model'].sudo().search([('model', '=', records._name)], limit=1)
        values = {
            'type': context['type'],
            'version_id': '',
            'res_model': records._name,
            'res_id': records.id,
            'model_id': records_model.id,
            'name': records.name,
            'user_id': self._uid,
            'end_date': datetime.now(),
            'start_state': start_state,
            'end_state': end_state,
            'note': context['message'],
            'state': '已提交',
            'sequence': 100,
        }
        self.env['workflow.info'].create(values)

        return True
